package com.nf.factory;

import com.nf.Annotation.ClassAnnotation;
import com.nf.Annotation.Destroy;
import com.nf.Annotation.Initialization;
import com.nf.Annotation.Scope;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 分原型和单例实例化类
 */
public class NewBean {
    //单例容器
    private static Map<String,Object> map=new HashMap<String,Object>();

    //通过Class对象获取实例
    public static <T> T getBean(Class<?> clazz){
        Object o = null;
        try {
            o = setMapBean(clazz);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) o;
    }

    //把单例的存放到map集合
    private static <T> T setMapBean(Class<?> clazz) throws Exception{
        //执行初始化方法
        NewBean.initialization(clazz);
        Object o=null;

        //没Scope注解就默认为原型,没值默认值也为原型
        if(clazz.isAnnotationPresent(Scope.class)){
            Scope annotation = clazz.getAnnotation(Scope.class);
            //如果为单例
            if(annotation.prototype().equals("singleton")) {
                //如果第一次加载
                if (map.get(clazz.getSimpleName()) == null||(map.get(clazz.getAnnotation(ClassAnnotation.class).value()).equals(""))) {
                    //如果ClassAnnotation的value值为空
                    map.put(getKey(clazz)   , clazz.newInstance());
                    o=map.get(getKey(clazz));
                }else {
                    o=map.get(getKey(clazz));
                }
            }else{
                o=clazz.newInstance();
            }
        }else{
            o=clazz.newInstance();
        }
        return (T) o;
    }

    private static String getKey(Class<?> clazz){
        String key=null;
        if(clazz.isAnnotationPresent(ClassAnnotation.class)){
            if(clazz.getAnnotation(ClassAnnotation.class).value().equals("")){
                key=toLowerBeanName(clazz.getSimpleName());
            } else {
                key=clazz.getAnnotation(ClassAnnotation.class).value();
            }
        }else {
            key=clazz.getSimpleName();
        }
        return key;
    }

    /**
     * 截取字符串
     * @param beanName
     * @return
     */
    private static String toLowerBeanName(String beanName) {
        beanName = beanName.substring(0, 1).toLowerCase()
                + beanName.substring(1);
        return beanName;
    }

    /**
     * 初始化方法
     */
    private static void initialization(Class<?> aClass) {
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for(int i=0;i<declaredMethods.length;i++) {
            if(declaredMethods[i].isAnnotationPresent(Initialization.class)){
                try {
                    declaredMethods[i].invoke(aClass.newInstance());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     *销毁方法
     */
    private static void destroyMethod() throws InvocationTargetException, IllegalAccessException {
        //如果类是单例的那么就会打印正在销毁
        //原型的是打印不出的
        for(String key:map.keySet()){
            Object o = map.get(key);
            Class<?> aClass = o.getClass();
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for(int i=0;i<declaredMethods.length;i++) {
                if(declaredMethods[i].isAnnotationPresent(Destroy.class)){
                    declaredMethods[i].invoke(o);
                }
            }
        }
    }

    /**
     *关闭map集合
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static void close() throws InvocationTargetException, IllegalAccessException {
        destroyMethod();
        map.clear();
    }
}
